package projorientado.util;

import java.util.Iterator;
import java.util.LinkedList;

public class CodeTokenizer {

    public static interface CodeElement {
        
        public String toString(String tab);
        
    }
    
    public static class CodeBlock implements CodeElement {
        
        public String name;
        public LinkedList<CodeElement> childs = new LinkedList();
        
        @Override
        public String toString() {
            return toString("");
        }
        
        public String toString(String tab) {
            StringBuilder r = new StringBuilder();
            r.append(tab);
            r.append(name);
            r.append("\n");
            r.append(tab);
            r.append("{\n");
            String newtab = tab + "\t";
            Iterator<CodeElement> it = childs.iterator();
            while(it.hasNext()) {
                CodeElement e = it.next();
                r.append(e.toString(newtab));
                r.append("\n");
            }
            r.append(tab);
            r.append("}");
            return r.toString();
        }
        
    }
    
    public static class CodeTextBlock implements CodeElement {
        
        public String text;
        public String name;
        
        @Override
        public String toString() {
            return text;
        }
        
        public String toString(String tab) {
            String[] lines = text.split("\n");
            StringBuilder r = new StringBuilder();
            r.append(tab);
            r.append(name);
            r.append("\n");
            r.append(tab);
            r.append("{\n");
            for(String line : lines) {
                r.append(tab);
                r.append("\t");
                r.append(line);
                r.append("\n");
            }
            r.append(tab);
            r.append("}");
            return r.toString();
        }
        
    }
    
    public static class CodeLine implements CodeElement {
        
        public String line;
        
        @Override
        public String toString() {
            return toString("");
        }

        public String toString(String tab) {
            return tab + line + ";";
        }
        
    }
    
    public static class CodeVarDef {
        public String varName;
        public String value;
    }
    
    public static CodeBlock singleParse(String text) {
        CodeTextBlock block = new CodeTextBlock();
        block.name = "root";
        block.text = text;
        return singleParse(block);
    }
    
    public static CodeBlock singleParse(CodeTextBlock block) {
        CodeBlock root = new CodeBlock();
        root.name = block.name;
        String text = block.text;
        
        boolean escapeString = false;
        boolean readingString = false;
        int lastPosition = 0;
        
        for(int i = 0; i < text.length(); i++) {
            char c = text.charAt(i);
            if(readingString) {
                if(c == '\\') {
                    if(escapeString)
                        escapeString = false;
                    else
                        escapeString = true;
                } else if(c == '"') {
                    if(escapeString)
                        escapeString = false;
                    else
                        readingString = false;
                }
            } else {
                if(c == '"') {
                    readingString = true;
                } else if(c == '{') {
                    String name = text.substring(lastPosition,i).trim();
   
                    int kcount = 1;
                    int init = i+1;
                    for(i++;i < text.length(); i++) {
                        c = text.charAt(i);
                        if(c == '{') {
                            kcount++;
                        } else if(c == '}') {
                            kcount--;
                            if(kcount == 0)
                                break;
                        }
                    }
                    
                    String codeText = text.substring(init,i);
                    
                    CodeTextBlock cText = new CodeTextBlock();
                    cText.name = name;
                    cText.text = codeText;
                    
                    root.childs.add(cText);
                    
                    lastPosition = i+1;
                } else if(c == ';') {
                    String line = text.substring(lastPosition,i).trim();
                    CodeLine cLine = new CodeLine();
                    cLine.line = line;
                    root.childs.add(cLine);
                    lastPosition = i+1;
                }
            }
        }
        
        if(lastPosition != text.length()) {
            String line = text.substring(lastPosition).trim();
            CodeLine cLine = new CodeLine();
            cLine.line = line;
            root.childs.add(cLine);
        }
        
        return root;
    }
    
    public static CodeVarDef parseVarDef(String str) {
        CodeVarDef v = new CodeVarDef();
        int p = str.indexOf("=");
        if(p == -1) {
            v.varName = str;
            return v;
        }
        v.varName = str.substring(0,p).trim();
        v.value = str.substring(p+1).trim();
        
        if(v.value.startsWith("\"") && v.value.endsWith("\"")) {
            v.value = v.value.substring(1,v.value.length()-1);
        }
        
        return v;
    }
    
    public static void main(String[] s) {
        String code = "x; \"kk\\\"k;{\"; bloco1 { x; u {}; kk; }; bloco2 {}";
        
        CodeBlock root = singleParse(code);
        
        System.out.println(root);
    }
    
}
